﻿using System;
using System.Collections.Generic;
using System.Linq;
using CapstoneProjectAEReader.Entities.Models;
using CapstoneProjectAEReader.Common.Utility;

namespace CapstoneProjectAEReader.DataAccess.DBAccess
{
    public class DAO
    {
        #region Attributes

        private DTO _dto = new DTO();
        private static FileHandler _fileHandler = new FileHandler();

        #endregion

        #region Methods

        public DAO(DTO dto)
        {
            _dto = dto;
        }

        public DTO Dto
        {
            get { return _dto; }
            set { _dto = value; }
        }

        public static void CommitData(DTO dto)
        {
            string dtFilePath = Utilities.GetCurrentLocation() + Constants.CommonCharacters.SlashString +
                                Constants.StorageStructure.ApplicationData;
            _fileHandler.WriteFile(dtFilePath, dto);
        }

        public List<Ebook> SelectEbookOfGroup(string groupName)
        {
            return _dto.Ebooks.FindAll(e => e.Group.Contains(groupName));
        }

        // Method for Insert , Update , Delete a table

        #region Ebook

        /// <summary>
        /// Check if ebook exists or not
        /// </summary>
        /// <param name="temp"></param>
        /// <returns></returns>
        public bool CheckEbookExist(Ebook temp)
        {
            return _dto.Ebooks.Any(e => e.Title == temp.Title && e.Author == temp.Author);
        }

        public int InsertEbook(Ebook temp)
        {
            if (_dto.Ebooks.Count > 0)
            {
                temp.Id = _dto.SettingDetail.MaxEbookId + 1;
                _dto.SettingDetail.MaxEbookId = temp.Id;
            }
            else
            {
                temp.Id = 1;
                _dto.SettingDetail.MaxEbookId = 1;
            }
            _dto.Ebooks.Add(temp);
            CommitData(_dto);
            return temp.Id;
        }

        public Boolean CheckEbookExistByTitle(string title)
        {
            return _dto.Ebooks.Any(e => e.Title == title);
        }

        public Ebook SelectEbook(string title, string author)
        {
            return _dto.Ebooks.Find(e => e.Title == title && e.Author == author);
        }

        public Ebook GetEbookById(int id)
        {
            return _dto.Ebooks.Find(e => e.Id == id);
        }

        public void UpdateEbook(Ebook temp)
        {
            Ebook x = _dto.Ebooks.Find(e => e.Id == temp.Id);
            int index = _dto.Ebooks.IndexOf(x);
            _dto.Ebooks[index] = temp;
            CommitData(_dto);
        }

        public void RemoveGroupOfEbook(Ebook temp, EbookGroup tempGroup)
        {
            Ebook x = _dto.Ebooks.Find(e => e.Id == temp.Id);
            int index = _dto.Ebooks.IndexOf(x);
            if (temp.Group.Contains(tempGroup.Groupname))
            {
                temp.Group.Remove(tempGroup.Groupname);
                temp.GroupInText = Utilities.ReturnGroupInText(temp.Group);
            }
            _dto.Ebooks[index] = temp;
            CommitData(_dto);
        }

        public void DeleteEbook(Ebook temp)
        {
            Ebook x = _dto.Ebooks.Find(e => e.Id == temp.Id);
            int index = _dto.Ebooks.IndexOf(x);
            _dto.Ebooks.RemoveAt(index);
            CommitData(_dto);
        }

        public List<Ebook> SearchEbookByAuthor(string text)
        {
            return (from x in _dto.Ebooks
                    where x.Author.Contains(text)
                    select x).ToList();
        }

        public List<Ebook> SearchEbookByTitle(string text)
        {
            return (from x in _dto.Ebooks
                    where x.Title.Contains(text)
                    select x).ToList();
        }

        public List<Ebook> SearchEbookByDate(DateTime selectedTime)
        {
            return (from x in _dto.Ebooks
                    where DateTime.Parse(x.ImportDate) < selectedTime
                    select x).ToList();
        }

        #endregion

        #region EbookGroup

        public bool CheckEbookGroupExist(string groupName)
        {
            return _dto.EbookGroup.Any(e => e.Groupname == groupName);
        }

        public int InsertEbookGroup(EbookGroup temp)
        {
            if (_dto.EbookGroup.Count > 0)
            {
                temp.Groupid = _dto.SettingDetail.MaxEbookGroupId + 1;
                _dto.SettingDetail.MaxEbookGroupId = temp.Groupid;
            }
            else
            {
                temp.Groupid = 1;
                _dto.SettingDetail.MaxEbookGroupId = 1;
            }
            _dto.EbookGroup.Add(temp);
            CommitData(_dto);
            return temp.Groupid;
        }

        public void UpdateEbookGroup(EbookGroup temp)
        {
            EbookGroup x = _dto.EbookGroup.Find(e => e.Groupid == temp.Groupid);
            int index = _dto.EbookGroup.IndexOf(x);
            foreach (Ebook ebook in _dto.Ebooks)
            {
                if (ebook.Group.Contains(x.Groupname))
                {
                    ebook.Group.Remove(x.Groupname);
                    ebook.Group.Add(temp.Groupname);
                    ebook.GroupInText = Utilities.ReturnGroupInText(ebook.Group);
                }
            }
            _dto.EbookGroup[index] = temp;
            CommitData(_dto);
        }

        public void DeleteEbookGroup(EbookGroup temp)
        {
            EbookGroup x = _dto.EbookGroup.Find(e => e.Groupid == temp.Groupid);
            List<Ebook> ebooks = _dto.Ebooks.FindAll(e => e.Group.Contains(temp.Groupname));
            foreach (var ebook in ebooks)
            {
                ebook.Group.Remove(temp.Groupname);
                if (ebook.Group.Count == 0)
                {
                    ebook.Group.Add(Constants.UnGroup);
                }
                ebook.GroupInText = String.Join(Constants.CommonCharacters.Comma, ebook.Group);
            }
            int index = _dto.EbookGroup.IndexOf(x);
            _dto.EbookGroup.RemoveAt(index);
            CommitData(_dto);
        }

        public int CountMembers(EbookGroup temp)
        {
            return (from x in _dto.Ebooks
                    where x.Group.Contains(temp.Groupname)
                    select x).Count();
        }

        public List<Ebook> GetEbookOfGroup(EbookGroup temp)
        {
            return (from x in _dto.Ebooks
                    where x.Group.Contains(temp.Groupname)
                    select x).ToList();
        }

        public EbookGroup SelectEbookGroup(string groupName)
        {
            return _dto.EbookGroup.Find(e => e.Groupname == groupName);
        }

        #endregion

        #region NoteDetail

        public bool CheckNoteDetailExist(int noteId, int bookId)
        {
            return _dto.NoteDetail.Any(e => e.Bookid == bookId && e.Noteid == noteId);
        }

        public NoteDetail GetNoteDetail(int noteId, int bookId)
        {
            return _dto.NoteDetail.Find(e => e.Bookid == bookId && e.Noteid == noteId);
        }

        public List<Note> GetNoteOfEbook(int bookId)
        {
            List<int> noteIds = (from e in _dto.NoteDetail
                                 where e.Bookid == bookId
                                 select e.Noteid).Distinct().ToList();
            return noteIds.Select(GetNoteById).ToList();
        }

        public List<NoteDetail> GetNoteDetailWithId(int noteId)
        {
            return _dto.NoteDetail.FindAll(e => e.Noteid == noteId);
        }

        public List<NoteDetail> GetNoteDetailWithBookId(int bookId)
        {
            return _dto.NoteDetail.FindAll(e => e.Bookid == bookId);
        }

        public void InsertNoteDetail(NoteDetail temp)
        {
            _dto.NoteDetail.Add(temp);
            CommitData(_dto);
        }

        public void DeleteNoteDetail(NoteDetail temp)
        {
            NoteDetail x = _dto.NoteDetail.Find(e => e.Noteid == temp.Noteid);
            int index = _dto.NoteDetail.IndexOf(x);
            _dto.NoteDetail.RemoveAt(index);
            CommitData(_dto);
        }

        public void UpdateNoteDetail(NoteDetail temp)
        {
            NoteDetail x = _dto.NoteDetail.Find(e => e.Noteid == temp.Noteid && e.Bookid == temp.Bookid);
            int index = _dto.NoteDetail.IndexOf(x);
            _dto.NoteDetail[index] = temp;
            CommitData(_dto);
        }

        #endregion

        #region Note

        public bool CheckNoteExist(string notedWord)
        {
            return _dto.Note.Any(e => e.NoteContent == notedWord);
        }

        public Note GetNote(string text)
        {
            return _dto.Note.Find(e => e.NoteContent == text);
        }

        public Note GetNoteById(int id)
        {
            return _dto.Note.Find(e => e.NoteId == id);
        }

        public int InsertNote(Note temp)
        {
            if (_dto.Note.Count > 0)
            {
                temp.NoteId = _dto.SettingDetail.MaxNoteId + 1;
                _dto.SettingDetail.MaxNoteId = temp.NoteId;
            }
            else
            {
                temp.NoteId = 1;
                _dto.SettingDetail.MaxNoteId = 1;
            }
            _dto.Note.Add(temp);
            CommitData(_dto);
            return temp.NoteId;
        }

        public void UpdateNote(Note temp)
        {
            Note x = _dto.Note.Find(e => e.NoteId == temp.NoteId);
            int index = _dto.Note.IndexOf(x);
            _dto.Note[index] = temp;
            CommitData(_dto);
        }

        public void DeleteNote(Note temp)
        {
            Note x = _dto.Note.Find(e => e.NoteId == temp.NoteId);
            int index = _dto.Note.IndexOf(x);
            _dto.Note.RemoveAt(index);
            CommitData(_dto);
        }

        public List<Note> SearchNote(string text)
        {
            return (from x in _dto.Note
                    where x.NoteContent.Contains(text)
                    select x).ToList();
        }

        #endregion

        #region BookMark

        public void InsertBookMark(Bookmark temp)
        {
            _dto.Bookmark.Insert(0, temp);
            CommitData(_dto);
        }

        public void UpdateBookmark(Bookmark temp)
        {
            Bookmark x = _dto.Bookmark.Find(e => e.Bookmarkid == temp.Bookmarkid);
            int index = _dto.Bookmark.IndexOf(x);
            _dto.Bookmark[index] = temp;
            CommitData(_dto);
        }

        public void DeleteBookmark(Bookmark temp)
        {
            Bookmark x = _dto.Bookmark.Find(e => e.Bookmarkid == temp.Bookmarkid);
            int index = _dto.Bookmark.IndexOf(x);
            _dto.Bookmark.RemoveAt(index);
            CommitData(_dto);
        }

        #endregion

        #region SettingDetail

        public void UpdateSettingDetail(SettingDetail temp)
        {
            _dto.SettingDetail = temp;
            CommitData(_dto);
        }

        public void RemoveRecentReadItem(Ebook temp)
        {
            if (_dto.SettingDetail.RecentRead.Contains(temp))
            {
                _dto.SettingDetail.RecentRead.Remove(temp);
            }
            CommitData(_dto);
        }

        #endregion

        #endregion
    }
}